#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <time.h>

#include <unistd.h>

#include "proto.h"

#define IPSTRSIZE 40
#define BUFSIZE 1024
#define PROCNUM 4

static void server_loop(int sd);

int main()
{
    int sd = socket(AF_INET, SOCK_STREAM, 0 /*IPPROTO_TCP, IPPROTO_SCTP*/);
    if (sd < 0)
    {
        perror("socket()");
        exit(1);
    }

    int val = 1;
    if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0)
    {
        perror("setsockopt()");
        exit(1);
    }

    struct sockaddr_in laddr;
    laddr.sin_family = AF_INET;
    laddr.sin_port = htons(SERVERPORT);
    inet_pton(AF_INET, "0.0.0.0", &laddr.sin_addr);

    if (bind(sd, (struct sockaddr *)&laddr, sizeof(laddr)) < 0)
    {
        perror("bind()");
        exit(1);
    }

    if (listen(sd, 200) < 0)
    {
        perror("listen()");
        exit(1);
    }

    // pid_t pid;
    // for (int i = 0; i < PROCNUM; i++)
    // {
    //     pid = fork();
    //     if (pid < 0)
    //     {
    //         perror("fork()");
    //         exit(1);
    //     }

    //     if (pid == 0)
    //     {
    //         server_loop(sd);
    //         exit(0);
    //     }
    // }

    // for (int i = 0; i < PROCNUM; i++)
    // {
    //     wait();
    // }
    server_loop(sd);
    close(sd);
    exit(0);
}

static void server_loop(int sd)
{
    struct sockaddr_in raddr;
    int raddr_len = sizeof(raddr);
    char ipstr[IPSTRSIZE];
    int newsd = 0;

    while (1)
    {
        newsd = accept(sd, (struct sockaddr *)&raddr, &raddr_len);
        if (newsd < 0)
        {
            perror("accept()");
            exit(1);
        }

        inet_ntop(AF_INET, &raddr.sin_addr, ipstr, IPSTRSIZE);
        printf("[%d]Client:%s:%d\n", getpid(), ipstr, ntohs(raddr.sin_port));

        char buf[BUFSIZ];
        int len = sprintf(buf, FMT_STAMP, (long long)time(NULL));

        if (send(newsd, buf, len, 0) < 0)
        {
            perror("send()");
            exit(1);
        }

        close(newsd);
    }
}